/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.erickpardal.game.fpsdemo;

import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.KeyInputListener;
import com.jme.input.MouseInput;
import com.jme.input.MouseInputListener;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.CameraNode;
import com.jme.scene.Controller;
import com.jme.scene.Line;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.Text;
import com.jme.scene.TriMesh;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.BufferUtils;
import com.jmex.effects.particles.ParticleFactory;
import com.jmex.effects.particles.ParticleMesh;
import com.jmex.model.animation.JointController;
import com.jmex.model.animation.KeyframeController;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Iterator;
import jmetest.effects.TestParticleSystem;

/**
 *
 * @author Erick Pardal
 */
public class Player {

    private Node rootNode, hudweapon,  weapon,  body;
    private CameraNode camNode;
    private JointController kcWeapon;
    private boolean move[] = new boolean[4];
    private int accuracy = 5;
    private int balas = 90;
    private int pente = 32;
    private int currentPente = 32;
    private long lastFire,  lastReload,  lastCock,  lastStopFire,  lastSelect;
    private boolean select = false;
    private boolean selectAnim = false;
    private boolean fire = false;
    private boolean fireAnim = false;
    private boolean autoFireAnim = false;
    private boolean stopFireAnim = false;
    private boolean reload = false;
    private boolean reloadAnim = false;
    private boolean cock = false;
    private boolean cockAnim = false;
    private boolean moveAnim = false;
    private Text textFire;
    private Text textReload;
    private Text textBalas;
    private Text textPente;

    public void setHUDWeapon(Node hudweapon) {
        this.hudweapon = hudweapon;
    }

    public void setWeapon(Node weapon) {
        this.weapon = weapon;

    }

    public void setBody(Node body) {
        this.body = body;
    }

    public void init(Node rootNode) {
        this.rootNode = rootNode;
        paintCrossHair(rootNode);
        textFire = Text.createDefaultTextLabel("textFire");
        textFire.setLocalTranslation(new Vector3f(2, 0, 0));
        textFire.setLightCombineMode(Spatial.LightCombineMode.Off);
        textFire.setRenderQueueMode(Renderer.QUEUE_ORTHO);
        rootNode.attachChild(textFire);
        textReload = Text.createDefaultTextLabel("textReload");
        textReload.setLocalTranslation(new Vector3f(2, 20, 0));
        textReload.setLightCombineMode(Spatial.LightCombineMode.Off);
        rootNode.attachChild(textReload);
        textBalas = Text.createDefaultTextLabel("textBalas");
        textBalas.setLocalTranslation(new Vector3f(2, 40, 0));
        textBalas.setLightCombineMode(Spatial.LightCombineMode.Off);
        rootNode.attachChild(textBalas);
        textPente = Text.createDefaultTextLabel("textPente");
        textPente.setLocalTranslation(new Vector3f(2, 60, 0));
        textPente.setLightCombineMode(Spatial.LightCombineMode.Off);
        rootNode.attachChild(textPente);

        if (hudweapon != null && !camNode.hasChild(hudweapon)) {
            camNode.attachChild(hudweapon);
            kcWeapon = (JointController) hudweapon.getController(0);
            //kcWeapon.setRepeatType(Controller.RT_WRAP);

            KeyInput.get().addListener(new KeyInputListener() {

                public void onKey(char character, int keyCode, boolean pressed) {
                    if (keyCode == KeyInput.KEY_W) {
                        if (pressed) {
                            if (!move[0]) {
                                move[0]=true;
                            }
                        } else {
                            moveAnim = false;
                            move[0] = false;
                        }
                    }
                    if (keyCode == KeyInput.KEY_S) {
                        if (pressed) {
                            if (!move[1]) {
                                move[1] = true;
                            }
                        } else {
                            moveAnim = false;
                            move[1] = false;
                        }
                    }
                    if (keyCode == KeyInput.KEY_A) {
                        if (pressed) {
                            if (!move[2]) {
                                move[2] = true;
                            }
                        } else {
                            moveAnim = false;
                            move[2] = false;
                        }
                    }
                    if (keyCode == KeyInput.KEY_D) {
                        if (pressed) {
                            if (!move[3]) {
                                move[3] = true;
                            }
                        } else {
                            moveAnim = false;
                            move[3] = false;
                        }
                    }
                    if (keyCode == KeyInput.KEY_R && pressed) {
                        if (currentPente < pente && balas > 0) {
                            if (!reload) {
                                reload = true;
                            }
                        }
                    }
                }
            });

            MouseInput.get().addListener(new MouseInputListener() {

                public void onButton(int button, boolean pressed, int x, int y) {
                    if (button == 0) {
                        if (pressed) {
                            if (reload) {
                                return;
                            }
                            if (currentPente > 0) {
                                if (!fire) {
                                    fire = true;
                                }
                            } else if (balas > 0) {
                                reload = true;
                            }
                        } else {
                            autoFireAnim = false;
                            fireAnim = false;
                            lastStopFire = System.currentTimeMillis();
                            stopFireAnim = true;
                        }
                    }
                }

                public void onWheel(int wheelDelta, int x, int y) {
                    //throw new UnsupportedOperationException("Not supported yet.");
                }

                public void onMove(int xDelta, int yDelta, int newX, int newY) {
                    //throw new UnsupportedOperationException("Not supported yet.");
                }
            });

        } else {
        }
    }

    private void paintCrossHair(Node node) {
        float lineWidth = 2;
        float max = 15, min = 5;
        ColorRGBA lineColor = ColorRGBA.lightGray;

        FloatBuffer vbUp = BufferUtils.createVector3Buffer(2);
        vbUp.put(0).put(max).put(0);//0
        vbUp.put(0).put(min).put(0);//1

        FloatBuffer vbDown = BufferUtils.createVector3Buffer(2);
        vbDown.put(0).put(-(max)).put(0);//0
        vbDown.put(0).put(-(min)).put(0);//1

        FloatBuffer vbLeft = BufferUtils.createVector3Buffer(2);
        vbLeft.put(-(max)).put(0).put(0);//0
        vbLeft.put(-(min)).put(0).put(0);//1

        FloatBuffer vbRigth = BufferUtils.createVector3Buffer(2);
        vbRigth.put(max).put(0).put(0);//0
        vbRigth.put(min).put(0).put(0);//1

        IntBuffer ibAll = BufferUtils.createIntBuffer(2);
        ibAll.put(0).put(1);

        Line lineUp = new Line("CrossHairUp");
        lineUp.setVertexBuffer(vbUp);
        lineUp.setIndexBuffer(ibAll);
        lineUp.setLineWidth(lineWidth);
        lineUp.setDefaultColor(lineColor);

        Line lineDown = new Line("CrossHairDown");
        lineDown.setVertexBuffer(vbDown);
        lineDown.setIndexBuffer(ibAll);
        lineDown.setLineWidth(lineWidth);
        lineDown.setDefaultColor(lineColor);

        Line lineLeft = new Line("CrossHairLeft");
        lineLeft.setVertexBuffer(vbLeft);
        lineLeft.setIndexBuffer(ibAll);
        lineLeft.setLineWidth(lineWidth);
        lineLeft.setDefaultColor(lineColor);

        Line lineRigth = new Line("CrossHairRigth");
        lineRigth.setVertexBuffer(vbRigth);
        lineRigth.setIndexBuffer(ibAll);
        lineRigth.setLineWidth(lineWidth);
        lineRigth.setDefaultColor(lineColor);

        Node crossHair = new Node("CrossHair");
        crossHair.attachChild(lineUp);
        crossHair.attachChild(lineDown);
        crossHair.attachChild(lineLeft);
        crossHair.attachChild(lineRigth);
        crossHair.setLocalTranslation(new Vector3f(DisplaySystem.getDisplaySystem().getWidth() / 2f - 8f,
                DisplaySystem.getDisplaySystem().getHeight() / 2f - 8f, 0));
        crossHair.setLightCombineMode(Spatial.LightCombineMode.Off);
        crossHair.setRenderQueueMode(Renderer.QUEUE_ORTHO);
        node.attachChild(crossHair);

    /*Text cross = Text.createDefaultTextLabel("Crosshairs", "+");
    cross.setTextColor(ColorRGBA.darkGray);

    cross.setLocalTranslation(new Vector3f(DisplaySystem.getDisplaySystem().getWidth() / 2f - 8f,
    DisplaySystem.getDisplaySystem().getHeight() / 2f - 8f, 0));
    cross.setLightCombineMode(Spatial.LightCombineMode.Off);
    cross.setRenderQueueMode(Renderer.QUEUE_ORTHO);
    node.attachChild(cross);*/

    }

    private static ParticleMesh createWeaponFireEffect() {
        ParticleMesh explosion = ParticleFactory.buildParticles("WeaponFireEffect", 150);
        explosion.setEmissionDirection(new Vector3f(1.0f, 1.0f, 0.0f));
        explosion.setMaximumAngle(360f * FastMath.DEG_TO_RAD);
        explosion.setSpeed(0.7f);
        explosion.setStartSize(2.0f);
        explosion.setEndSize(4.0f);
        explosion.setStartColor(new ColorRGBA(1.0f, 0.312f, 0.121f, 1.0f));
        explosion.setEndColor(new ColorRGBA(1.0f, 0.24313726f, 0.03137255f, 0.0f));
        explosion.setReleaseVariance(0.5f);
        explosion.getParticleController().setControlFlow(false);
        explosion.setParticleSpinSpeed(0.2f);
        explosion.setRepeatType(Controller.RT_CLAMP);


        explosion.warmUp(1000);
        TriMesh particles = explosion.getParticleGeometry();
        particles.addController(explosion.getParticleController());

        TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
        ts.setTexture(
                TextureManager.loadTexture(
                TestParticleSystem.class.getClassLoader().getResource(
                "jmetest/data/texture/flaresmall.jpg"),
                Texture.MinificationFilter.Trilinear,
                Texture.MagnificationFilter.Bilinear));
        ts.setEnabled(true);

        BlendState as = DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
        as.setBlendEnabled(true);
        as.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
        as.setDestinationFunction(BlendState.DestinationFunction.One);
        as.setTestEnabled(true);
        as.setTestFunction(BlendState.TestFunction.GreaterThan);
        as.setEnabled(true);
        as.setEnabled(true);

        ZBufferState zstate = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
		zstate.setWritable(false);
		zstate.setEnabled(true);
		zstate.setFunction(ZBufferState.TestFunction.EqualTo);

        explosion.setRenderState(ts);
        explosion.setRenderState(as);
        explosion.setRenderState(zstate);
        explosion.updateRenderState();
        //explosion.setModelBound(new BoundingSphere());
        //explosion.updateModelBound();

        return explosion;
    }

    private void fire() {
        ParticleMesh fireEffect = createWeaponFireEffect();
        Vector3f fireEffectPos = new Vector3f(hudweapon.getLocalTranslation());
        fireEffectPos.y += 11.1f; // z axis from the gun in this case here
        fireEffectPos.z -= 2.8f;
        fireEffect.setLocalTranslation(fireEffectPos);
        fireEffect.forceRespawn();
        hudweapon.attachChild(fireEffect);
    }

    public void reload() {
        if (balas > 0 && currentPente < pente) {
            reload = true;

            if (balas >= pente) {
                int aux = (pente - currentPente);
                currentPente +=
                        aux;
                balas -=
                        aux;
            } else {
                currentPente = balas;
                balas =
                        0;
            }
        }
    }

    public void setCamera(CameraNode camNode) {
        this.camNode = camNode;
    }

    public void update() {
        textFire.print("Fire: " + fire);
        textReload.print("Reload: " + reload);
        textBalas.print("Balas: " + balas);
        textPente.print("Pente: " + currentPente);

        boolean moving = move[0]||move[1]||move[2]||move[3];

        if (select || cock || reload || fire || moving) {
            if (select) {
                if (!selectAnim) {

                    kcWeapon.setTimes(0, 25);
                    lastSelect = System.currentTimeMillis();
                    selectAnim = true;
                } else if (System.currentTimeMillis() >= lastSelect + ((25 * 1000) / 20)) {
                    selectAnim = false;
                    select = false;
                }
            } else if (cock) {
                if (moveAnim) {
                    moveAnim = false;
                }
                if (!cockAnim) {
                    kcWeapon.setTimes(148, 182);
                    lastCock = System.currentTimeMillis();
                    cockAnim = true;
                } else if (System.currentTimeMillis() >= lastCock + ((34 * 1000) / 20)) {
                    cockAnim = false;
                    cock = false;
                }
            } else if (reload) {
                if (moveAnim) {
                    moveAnim = false;
                }
                if (!reloadAnim) {
                    kcWeapon.setTimes(81, 182);
                    lastReload = System.currentTimeMillis();
                    reloadAnim = true;
                    reload();
                } else if (System.currentTimeMillis() >= lastReload + ((100 * 1000) / 20)) {
                    reloadAnim = false;
                    reload = false;
                }
            } else if (fire) {
                if (moveAnim) {
                    moveAnim = false;
                }
                if (stopFireAnim) {
                    if (System.currentTimeMillis() >= lastStopFire + ((5 * 1000) / 20)) {
                        stopFireAnim = false;
                        fire = false;
                    }
                } else if (autoFireAnim) {
                    if (System.currentTimeMillis() >= lastFire + ((5 * 1000) / 20)) {
                        fire();
                        if (currentPente > 0) {
                            lastFire = System.currentTimeMillis();
                            --currentPente;
                        } else {
                            autoFireAnim = false;
                            fireAnim = false;
                            stopFireAnim = true;
                            if (balas > 0) {
                                fire = false;
                                reload = true;
                            } else {
                                kcWeapon.setTimes(75, 80);
                                lastStopFire = System.currentTimeMillis();
                                stopFireAnim = true;
                            }
                        }
                    }
                } else if (!fireAnim) {
                    fire();
                    kcWeapon.setTimes(66, 68);
                    lastFire = System.currentTimeMillis();
                    --currentPente;
                    fireAnim = true;
                } else if (System.currentTimeMillis() >= lastFire + ((2 * 1000) / 20)) {
                    if (currentPente > 0) {
                        fire();
                        kcWeapon.setTimes(69, 74);
                        autoFireAnim = true;
                    } else {
                        fireAnim = false;
                        if (balas > 0) {
                            fire = false;
                            reload = true;
                        } else {
                            kcWeapon.setTimes(75, 80);
                            lastStopFire = System.currentTimeMillis();
                            stopFireAnim = true;
                        }
                    }
                }
            } else if (moving) {
                if (!moveAnim) {
                    kcWeapon.setTimes(51, 65);
                    moveAnim = true;
                }
            }
        } else {
            kcWeapon.setTimes(26, 50);
        }
    }
}
